<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

class Article extends Model
{
    use SoftDeletes;

    protected $table = 'articles';

    /**
     * 定义主键
     * @var string
     */
    protected $primaryKey = 'id';

    /**
     * 禁止批量赋值的字段
     *
     * @var array
     */
    protected $guarded = ['id', 'created_at', 'deleted_at'];

    protected $fillable = ['id', 'article_title'];

    protected $appends = ['list_img_url','video_urls','zaned', 'liked', 'followed','collected', 'author', 'content_into', 'imgs_url','mp3_urls','content_into1'];
    /**
     * 软删除应该被调整为日期的属性
     * [$dates description]
     * @var [type]
     */
    protected $dates = [
        'created_at', 'updated_at', 'deleted_at'
    ];


    protected $expired = 43200; //redis 视频token有效期 12小时


    // 文章分类
    public function article_category()
    {
        return $this->hasOne('\App\Models\ArticleCategory', 'id', 'category_id');
    }


    // 文章分类
    public function articles_author()
    {
        return $this->hasOne('\App\Models\AdminUsers', 'id', 'admin_id');
    }

    // 所属地区
    public function region_info()
    {
        return $this->hasOne('\App\Models\SystemRegion', 'id', 'region_id');
    }


    public function getListImgUrlAttribute()
    {
        if ($this->list_img) {
            return config('app.img_url') . $this->list_img;
        } else {
            return false;
        }

    }
    
    public function getContentIntoAttribute()
    {
        $content_intro = strip_tags($this->content);
        $content_intro = str_replace('\r', '', $content_intro);
        $content_intro = str_replace('\n', '', $content_intro);
        $content_intro = str_replace('&ldquo;', '“', $content_intro);
        $content_intro = str_replace('&rdquo;', '”', $content_intro);
        return $content_intro;
    }
	public function getContentInto1Attribute()
    {
        $content_intro = strip_tags($this->content1);
        $content_intro = str_replace('\r', '', $content_intro);
        $content_intro = str_replace('\n', '', $content_intro);
        $content_intro = str_replace('&ldquo;', '“', $content_intro);
        $content_intro = str_replace('&rdquo;', '”', $content_intro);
        return $content_intro;
    }
    public function getImgsUrlAttribute()
    {
        $newarr = [];
        if($this -> attributes['imgs']){
            $arr = json_decode($this -> attributes['imgs']);
            foreach($arr as $v){
                $newarr[] = config('app.img_url') . $v;
            }
        }
        return $newarr;
    }

    public function getVideoUrlsAttribute()
    {
        return config('app.img_url') . $this->video_url;
    }
	public function getMp3UrlsAttribute()
    {
        return config('app.img_url') . $this->mp3_url;
    }

    public function getZanedAttribute()
    {

        if(!$user_id = auth() -> id()){
            return false;
        }

        return $zaned = ArticleOperateLog::where('article_id',$this->id) -> where('user_id',$user_id) -> where('operate_type',2) -> first()
            ? true : false;
    }

    public function getLikedAttribute()
    {

        if(!$user_id = auth() -> id()){
            return false;
        }
        // 图文1、商品2,'types'
        $obj_types =  1;

        return $liked = UserCollect::where('obj_id',$this->id) -> where('user_id',$user_id) -> where('obj_types',$obj_types) -> where('types',1) -> first()
            ? true : false;
    }


    public function getFollowedAttribute()
    {
        if(!$user_id = auth() -> id()){
            return false;
        }

        if(!$this -> admin_id){
            return false;
        }
        return $followed = UserFollow::where('follow_admin_id',$this -> admin_id) -> where('user_id',$user_id) -> first()
            ? true : false;
    }


    public function getCollectedAttribute()
    {
        if(!$user_id = auth() -> id()){
            return false;
        }
        // 文章1、商品2
        $obj_types =  1 ;

        return $collected = UserCollect::where('obj_id',$this->id) -> where('user_id',$user_id) -> where('obj_types',$obj_types) -> where('types',2) -> first()
            ? true : false;
    }


    public function getAuthorAttribute()
    {
        return AdminUsers::where('id',$this -> admin_id) -> value('name');
    }






    /**
     * 获得文章列表
     * @param int $articleType 0全部 1图文、视频文章， 2短视频文章
     * @param int $categoryId
     * @param int $regionId
     * @param int $pagesize
     * @param int $order 排序规则 1置顶>权重>发布时间
     * @param array $user
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public static function get_article_list($articleType = 0, $categoryId = 0, $regionId = 0, $pagesize = 5, $order = 1, $user = [],$istop=0)
    {
        $query = self::query();
        if ($articleType == 1) {
            // 图文、视频文章
            $query->where('types', '<', 3);
        } else if ($articleType == 2) {
            // 短视频文章
            $query->where('types', 3);
        }

        if ($categoryId) {
//            $is_region = ArticleCategory::region_check($categoryId);
//            if ($is_region) {
//                $query->where('region_id', $regionId);
//            }
            $query->where(function ($query_region) use ($regionId) {
                $query_region->where('region_id', 0);
                $query_region->orWhere('region_id', null);
                if ($regionId > 0) {
                    $query_region->orWhere('region_id', $regionId);
                }
            });
            $query->whereIn('category_id', ArticleCategory::getChild($categoryId));
        }

        if ($user && $user['user_id'] > 0) {
            if ($user['is_admin'] > 0) {
                $query->where('admin_id', $user['user_id']);
            } else {
                $query->where('user_id', $user['user_id']);
            }

            // 33app系统文章，31本村概况，20乡贤榜
            $query->whereNotIn('category_id', [33, 31, 20]);
        }
		if($istop==1){
			$query->where('is_top',1);
		}
        if ($order == 1) {
            $query->orderBy('is_top', 'desc');
            $query->orderBy('weight', 'desc');
            $query->orderBy('id', 'desc');
        }
        $query->where('is_show',1);

        $query->with(['articles_author', 'article_category']);
        $dataList = $query->paginate($pagesize);

        return $dataList;
    }

    public function article_data($request, $pagesize)
    {
        $category_id = $request->input('category_id');
        $region_id = $request->input('region_id');


        if ($request->has('category_id')) {
            $article = Article::where('category_id', $category_id);
            $is_region = ArticleCategory::region_check($category_id);
            if ($is_region) {
                $article->where('region_id', $region_id);
            }
        } else {
            $article = Article::where('category_id', '!=', 0);
        }
        $article -> where('is_show',1);

        // 获取多图
        if ($request->has('imgs')) {
            $article->where('imgs', '!=', '[]');
        }
        // 文章的类型
        if ($request->has('types')) {
            $article->whereIn('types', explode(',', $request->input('types')));
        } else {
            $article->where('types', 1); //默认图文类型
        }

        // 排序规则
        if ($request->has('order')) {

            $order = $request->input('order');
            $order = explode(',', $order);
            if ($request->has('by')) {

                $by = $request->input('by');
                $bys = explode(',', $by);
                if (count($bys) == 1) {
                    foreach ($order as $k => $v) {
                        $v && $article->orderBy($v, $bys[0]);
                    }
                } else {
                    foreach ($order as $k => $v) {
                        $v && $article->orderBy($v, $bys[$k]);
                    }
                }

            } else {
                foreach ($order as $k => $v) {
                    $v && $article->orderBy($v, 'desc');
                }
            }

        } else {
            $article->orderBy('id', 'desc');
        }

        $res = $article -> paginate($pagesize);

        return $res;
    }




    public function video_data($request)
    {

        $article_one = [];
        $video = Article::with(['articles_author:id,name,avatar']);
        $video -> select('id','article_title','list_img','imgs','video_url','category_id','region_id','zan_num','read_num','collect_num','like_num','share_num','content','admin_id','is_admin', 'user_id','types','imgs');


        if($request -> filled('video_ids_token')){


            $video_ids_token = $this -> video_ids_token('',$request -> input('video_ids_token'), ($request -> input('pagesize') ?: 5));

            if($video_ids_token){
                $video -> whereIn('id',$video_ids_token[0]);
                $video -> orderByRaw('field(id,'.implode(',',$video_ids_token[0]).')');
            }

        }else{

            if ($request->filled('article_id')) {
                $article_id  = $request -> input('article_id');
                $article_one = self::with(['articles_author:id,name,avatar'])
                    -> select('id','article_title','list_img','imgs','video_url','category_id','region_id','zan_num','read_num','collect_num','like_num','share_num','content','admin_id','is_admin', 'user_id','types','imgs')
                    -> find($article_id);

                // 获取某类型下的所有视频id
                $ids = self::where('category_id',$article_one -> category_id) -> where('id','!=',$article_id) -> orderBy('id','desc') -> pluck('id') -> toArray();
                $ids = [$article_one -> category_id => $ids];

                $video_ids_token = $this -> video_ids_token($ids,'', ($request -> input('pagesize') ?: 5));

                // 从redis读取视频id
                $video_ids_token && $video -> whereIn('id',$video_ids_token[0]);

            }else{
                return false;
            }

        }



        $video->where('types', 3); //默认短视频类型
        $video->where('is_show', 1); //展示


        $res = $video -> limit($request -> input('pagesize') ?:5) -> get() ->toArray();

        if(!$res) { return false; }

        if($article_one){
            array_unshift($res,$article_one -> toArray());
        }

        $video_ids_token && $res['video_ids_token'] = $video_ids_token[1];

        return $video_ids_token ? $res : false;


    }


    // 返回视频ids数组
    public function video_ids_token( $data, $token = '', $offset)
    {

        if($token){

            $video_ids = Redis::get($token);$ttl = Redis::ttl($token);
            $video_ids = json_decode($video_ids,true);
            if(!$video_ids){
                $video_ids = []; $ttl = $this -> expired;
            }


            $key = key($video_ids);

            // 当某类没有数据时，就查询其他类并存储到redis
            if($key == 0){
                $arr = $video_ids;

                if($arr){

                    $sub_video_ids = array_splice($arr,0, $offset);
                    $res = Redis::setex($token, $ttl, json_encode($arr,JSON_FORCE_OBJECT));

                }else{
                    // 当他类 视频刷完 存储所有随机的视频id
                    $video_ids = self::where('types',3) -> pluck('id') -> shuffle();
                    $sub_video_ids = $video_ids -> splice(0,$offset) -> all();

                    $res = Redis::setex($token, $ttl, json_encode($video_ids -> all(),JSON_FORCE_OBJECT));
                }

            }else{
                $arr = current($video_ids);
                if($arr){

                    $sub_video_ids = array_splice($arr,0, $offset);
                    $new_video_ids = [$key => $arr];

                    $res = Redis::setex($token, $ttl, json_encode($new_video_ids,JSON_FORCE_OBJECT));

                }else{
                    $video_ids = article::where('category_id','!=',$key) -> where('types',3) -> pluck('id');
                    if(!$video_ids){
                        $video_ids = article::where('types',3) -> pluck('id') -> shuffle();
                    }
                    $sub_video_ids = $video_ids -> splice(0,$offset) -> all();

                    $res = Redis::setex($token, $ttl, json_encode($video_ids ->all(),JSON_FORCE_OBJECT));
                }
            }


        }else{
            $arr  = current($data); $key = key($data);
            $sub_video_ids = array_splice($arr,0, $offset);
            $data = [$key => $arr];

            $token = randStr().'_videoIds';
            $res   = Redis::setex($token, $this -> expired, json_encode($data,JSON_FORCE_OBJECT));

        }

        return [$sub_video_ids,$token];

    }


    public function getVideoData($video_id,$offset,$token='')
    {

        $fields = ['id','article_title','list_img','imgs','video_url','category_id','region_id','zan_num','read_num','collect_num','like_num','share_num','content','admin_id','types'];


        // 有token的，优先以token为主
        if($token){

            $res = $this -> video_info_token('',$offset,$token);

            return $res;
        }else{
            // 没有token的，创建token

            // 有视频id的，先获取到这条视频，再获取相关类的视频1000条
            if($video_id){
                $limit = 1000;
                $video_one = self::with(['articles_author:id,name,avatar']) -> where('types',3) -> where('is_show',1) -> select($fields);
                $video_one = $video_one -> find($video_id);

                $video_more = self::with(['articles_author:id,name,avatar']) -> where('types',3) -> where('is_show',1) -> select($fields);
                $video_more = $video_more -> where('category_id',$video_one -> category_id) -> where('id','!=',$video_id) -> limit($limit) -> get();
                $video_more -> prepend($video_one);

                $return_video = $video_more -> splice(0,$offset) -> all();
                $redis_video  = $video_more -> all();

                // 存储数据
                $res = $this -> video_info_token([$video_one -> category_id => $redis_video], $offset);
                $res['video_list'] = $return_video;
                return $res;
            }else{
                return false;
            }
        }
    }


    // redis存储视频数据
    public function video_info_token($data, $offset, $token = '')
    {

        if($token){
            $limit  = 1000;  // 将1000条视频 存到redis
            $fields = ['id','article_title','list_img','imgs','video_url','category_id','region_id','zan_num','read_num','collect_num','like_num','share_num','content','admin_id','types'];


            $video_data = Redis::get($token);  $ttl = Redis::ttl($token);
            $video_data = json_decode($video_data,true);
            if(!$video_data){
                $video_data = []; $ttl = $this -> expired;
            }


            $key = key($video_data);

            if($key == 0){
                if($video_data){
                    $video_data  = collect($video_data);
                    $video_list = $video_data -> splice(0,$offset) -> all();
                    $redis_data  = $video_data -> all();

                }else{
                    $video_data = self::with(['articles_author:id,name,avatar']) -> where('types',3) -> where('is_show',1) -> select($fields);

                    $video_data = $video_data -> limit($limit) -> orderBy('id','desc') -> get() -> shuffle();
                    $video_list = $video_data -> splice(0,$offset) -> all();
                    $redis_data = $video_data -> all();
                }

                Redis::setex($token,$ttl,json_encode($redis_data,JSON_FORCE_OBJECT));
                return ['video_list' => $video_list,'video_info_token' => $token];
            }else{
                $video_data = current($video_data);

                if($video_data){
                    $video_data  = collect($video_data);
                    $video_list = $video_data -> splice(0,$offset) -> all();
                    $redis_data  = $video_data -> all();

                    $redis_data = [$key => $redis_data];
                }else{

                    $video_data = self::with(['articles_author:id,name,avatar']) -> where('types',3) -> where('is_show',1) -> select($fields);

                    $video_data = $video_data -> where('category_id','!=',$key) -> limit($limit) -> orderBy('id','desc') -> get();
                    $video_list = $video_data -> splice(0,$offset) -> all();
                    $redis_data = $video_data -> all();
                }


                Redis::setex($token,$ttl,json_encode($redis_data,JSON_FORCE_OBJECT));
                return ['video_list' => $video_list,'video_info_token' => $token];
            }
        }else{
            $token = randStr() . '_videoInfo';
            $res = Redis::setex($token, $this -> expired, json_encode($data,JSON_FORCE_OBJECT));

            return ['video_list' => [],'video_info_token' => $token];
        }
    }


    // 文章被各种操作  阅读1、点赞2、喜欢3、收藏4、分享5、作者关注6
    public static function article_operated($article_id, $type)
    {

        $inc_fields = [1 => 'read_num', 2 => 'zan_num', 3 => 'like_num', 4 => 'collect_num', 5 => 'share_num', 6 => 'follow_num'];

        switch($type){
            case 1:

                ArticleOperateLog::log(['id' => $article_id, 'type' => $type]); //记录日志
                self::where('id', $article_id) -> increment($inc_fields[$type]);
                $res = 1;
                break;
            case 2:

                IntegralRule::rule(4,auth() -> id(),$article_id);
                $article = self::where('id', $article_id);
                $logData = [
                    'article_id'   => $article_id,
                    'user_id'      => auth() -> id(),
                    'operate_type' => $type,
                ];
                if(ArticleOperateLog::where($logData) -> first()){
                    $res = $article -> decrement($inc_fields[$type]);
                }else{
                    $res = $article -> increment($inc_fields[$type]);
                }
                ArticleOperateLog::log(['id' => $article_id, 'type' => $type]);
                break;
            case 3:

                $collect_data = [
                    'obj_id' => $article_id,
                    'obj_types' =>  1,
                    'types' =>  1
                ];
                $res = UserCollect::up($collect_data);
                ArticleOperateLog::log(['id' => $article_id, 'type' => $type]);
                break;
            case 4:

                $collect_data = [
                    'obj_id' => $article_id,
                    'obj_types' => 1,
                    'types' => 2
                ];
                $res = UserCollect::up($collect_data);
                ArticleOperateLog::log(['id' => $article_id, 'type' => $type]); //记录日志
                break;
            case 5:
                // 分享送积分
                IntegralRule::rule(11,auth() -> id(),$article_id);
                $res = self::where('id', $article_id) -> increment($inc_fields[$type]);
                ArticleOperateLog::log(['id' => $article_id, 'type' => $type]); //记录日志
                break;
            case 6:
                $user_id = auth() -> id();

                // 监测用户是否已被关注  已被关注的，取消关注
                $followed_user_id = self::where('id',$article_id) -> value('admin_id');
                $res = UserFollow::followOrCancel($user_id,$followed_user_id);

                ArticleOperateLog::log(['id' => $article_id, 'type' => $type]); //记录日志
                break;
        }


        return $res;

    }

    // 获取子类文章
    public static function getChildArticle($pid, $region_id, $pagesize)
    {

        $category_ids = ArticleCategory::getChildCid($pid)->toArray();

        $childArticle = Article::whereIn('category_id', $category_ids) -> where('is_show',1);
        $childArticle -> select(['id','article_title','list_img','imgs','admin_id','content','category_id']);
        if ($region_id) {
            $childArticle->where('region_id', $region_id);
        }
        $res = $childArticle -> paginate($pagesize);

        return $res;
    }

    // 文章和视频交替展示
    public static function articleImgVideo($request, $pagesize)
    {

        $article = [];
        $category_id = $request->input('category_id');
        $fields = ['id','article_title','imgs','admin_id','video_url','created_at','updated_at'];

        $articleImg = Article::where('types', 1)->select($fields)->where('category_id', $category_id)->where('imgs', '!=', '') -> where('is_show',1)->paginate($pagesize);
        $articleVideo = Article::where('types', 2)->select($fields)->where('category_id', $category_id)->where('video_url', '!=', '') -> where('is_show',1)->paginate($pagesize);
        $count1 = count($articleImg);
        $count2 = count($articleVideo);

        if ($count1 || $count2) {
            for ($i = 0; $i < ($count1 > $count2 ? $count1 : $count2) * 2; $i++) {
                if ($i % 2 == 0) {
                    !empty($articleImg[$i / 2]) && $article[] = $articleImg[$i / 2];
                } else {
                    !empty($articleVideo[($i - 1) / 2]) && $article[] = $articleVideo[($i - 1) / 2];
                }
            }

            return $article;
        } else {
            return false;
        }
    }


    /**
     * 党务文章
     * @param int $regionId
     * @param int $categoryId
     * @param int $pageNum
     * @param int $pageSize
     * @param string $select
     * @return array
     */
    public static function getPartyArticlesPaginateByRegion(int $regionId = 0, int $categoryId = 0, int $pageNum = 10, int $pageSize = 10, string $select = '*'): array
    {
        $where = [];

        if (!$regionId) {
            return [];
        } else {
            $where['region_id'] = $regionId;
        }

        switch ($categoryId) {
            case 0:
                $categoryIds = [14, 15];
                $where[] = [function ($query) use ($categoryIds) {
                    $query->whereIn('category_id', $categoryIds);
                }];
                break;
            case 14:
            case 15:
                $where['category_id'] = $categoryId;
                break;

            default:
                return [];
        }

        $count = self::where($where)
            ->count();

        if ($count < 1) {
            return [];
        }

        if (empty($pageSize) || $pageSize > 100 || $pageSize < 1) {
            $pageSize = 10;
            $limit_size = 10;
        } else {
            $limit_size = $pageSize;
        }
        $total_page = ceil($count / $pageSize);
        if ($pageNum > $total_page) {
            return [];
        }

        if (empty($pageNum) || $pageNum < 1) {
            $pageNum = 1;
            $start = 0;
        } else {
            $start = $pageNum - 1;
        }
        $limit_start = $start * $limit_size;

        $party_articles = self::where($where)
            ->with(['articles_author' => function ($query) {
                $query->select('id', 'name as author'); // 需要同时查询关联外键的字段
            }])
            ->selectRaw($select)
            ->offset($limit_start)
            ->limit($limit_size)
            ->get();


        if ($party_articles->isEmpty()) {
            return [];
        } else {
            $party_articles = $party_articles->toArray();
        }

        foreach ($party_articles as $key => $article) {
            if (isset($article['content']) && !empty($article['content'])) {
                $party_articles[$key]['abstract'] = strip_tags($article['content']);
                $party_articles[$key]['abstract'] = preg_replace('/\s/', '', $party_articles[$key]['abstract']);
            } else {
                $party_articles[$key]['abstract'] = '';
            }

            $party_articles[$key]['author'] = $article['articles_author']['author'];
            unset($party_articles[$key]['content']);
            unset($party_articles[$key]['admin_id']);
            unset($party_articles[$key]['articles_author']);

        }

        return [
            #   数据
            'rows' => $party_articles,
            #   分页信息
            'pages' => [
                'now_page' => $pageNum,
                'total_page' => $total_page,
                'record_count' => $count
            ]
        ];
    }

    /**
     * PC端用 文章列表
     * @param array $whereData
     * whereData.categort_id 分类ID
     * whereData.author_id 作者ID
     * whereData.is_admin 作者类型 1管理员，0普通用户
     * whereData.keywords 关键词
     * whereData.types 文章类型（1图文，2视频，3短视频）
     * @param int $pagesize
     * @return mixed
     */
    public static function pc_article_list($whereData = [], $pagesize = 5)
    {
        $query = Article::where('is_show', 1);
        if (isset($whereData['categort_id']) && $whereData['categort_id']) {
            $childCategory = ArticleCategory::getChild($whereData['categort_id']);
            $query->whereIn('category_id', $childCategory);
        }
        if (isset($whereData['author_id']) && $whereData['author_id']) {
            // 33app系统文章，31本村概况，20乡贤榜
            $query->whereNotIn('category_id', [33, 31, 20]);
            if ($whereData['is_admin']) {
                $query->where('admin_id', $whereData['author_id']);
            } else {
                $query->where('user_id', $whereData['author_id']);
            }
        }
        if (isset($whereData['keywords']) && $whereData['keywords']) {
            $query->where('article_title', 'like', '%'.$whereData['keywords'].'%');
        }

        if (isset($whereData['types']) && $whereData['types'] > 0) {
            $query->where('types', $whereData['types']);
        }

        $query->with(['region_info', 'articles_author']);
//            ->select(['id', 'article_title', 'list_img', 'imgs', 'region_id', 'read_num', 'zan_num', 'collect_num', 'like_num', 'share_num', 'category_id', 'is_top', '', '', '', ''])
        $query->orderBy('is_top', 'desc');
        $query->orderBy('weight', 'desc');
        $query->orderBy('id', 'desc');
        $article_data = $query->paginate($pagesize);

        return $article_data;
    }

    /**
     * PC端 获得文章相关的全部图片
     * @param $article
     * @return array
     */
    public static function pc_article_get_all_imgs($article)
    {
        $all_img_url = array_merge($article->imgs_url, [$article->list_img_url]);
        preg_match_all('/<img.*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.png|\.jpeg|\.?]))[\'|\"].*?[\/]?>/', $article->content, $images);

        if (count($images[1]) > 0) {
            $images = array_unique($images[1]); // 去除重复图片地址
            $all_img_url = array_merge($all_img_url, $images);
        }

        return $all_img_url;
    }
	/*
	** 随机文章置顶
	*/
	public function rand_to_top(int $categoryId = 0,int $num=2){
		
		$query = self::query();
		$query->where('is_top',1);
        if ($categoryId) {
            $query->whereIn('category_id', ArticleCategory::getChild($categoryId));
        }
		$dataList=$query->update(['is_top'=>0]);
		$dataList1=self::query()->select(['id','imgs'])->whereIn('category_id', ArticleCategory::getChild($categoryId))->orderBy(DB::raw('RAND()'))->paginate($num)->toArray();
		 
		 foreach($dataList1['data'] as $k=>$v){
			 $aids[]=$v['id'];
		 } 
		 $article=self::query()->whereIn('id',$aids)->update(['is_top'=>1]);
		 return $article; 
	}
}
